#include "BlockQueue.hpp"
#include <ctime>
#include <unistd.h>

// void* producer(void* args)
// {
//     BlockQueue<int>* bq = static_cast<BlockQueue<int>*>(args);
//     while(true)
//     {
//         //生产活动
//         int data = rand() % 10 + 1;
//         bq->push(data);
//         std::cout << "生产数据：" << data << std::endl;
//         sleep(1);
//     }
// }

// void* consumer(void* args)
// {
//     BlockQueue<int>* bq = static_cast<BlockQueue<int>*>(args);
//     while(true)
//     {
//         //消费活动
//         int data;
//         bq->pop(&data);
//         std::cout << "消费数据：" << data << std::endl;
//         // sleep(1);
//     }
// }

// int main()
// {
//     srand((unsigned int)time(nullptr) % 1234);

//     BlockQueue<int>* bq = new BlockQueue<int>(); //让p和c看到一份公共的资源

//     pthread_t p,c;
//     pthread_create(&p, nullptr, producer, bq);
//     pthread_create(&c, nullptr, consumer, bq);

//     pthread_join(p,nullptr);
//     pthread_join(c,nullptr);
//     return 0;
// }

#include "Task.hpp"

// void *producer(void *args)
// {
//     BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
//     while (true)
//     {
//         // 生产活动
//         int x = rand() % 100 + 1;
//         int y = rand() % 5;
//         int operCode = rand() % oper.size();
//         Task t(x, y, oper[operCode], add);
//         bq->push(t);
//         std::cout << "生产任务：" << t.getTask() << std::endl;
//         sleep(1);
//     }
// }

// void *consumer(void *args)
// {
//     BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
//     while (true)
//     {
//         // 消费活动
//         Task out;
//         bq->pop(&out);
//         std::cout << "消费任务：" << out() << std::endl;
//         // sleep(1);
//     }
// }

// int main()
// {
//     srand((unsigned int)time(nullptr) % 1234);

//     BlockQueue<Task> *bq = new BlockQueue<Task>(); // 让p和c看到一份公共的资源

//     pthread_t p, c;
//     pthread_create(&p, nullptr, producer, bq);
//     pthread_create(&c, nullptr, consumer, bq);

//     pthread_join(p, nullptr);
//     pthread_join(c, nullptr);

//     delete bq;
//     return 0;
// }

template<class C, class S>
class BlockQueues
{
public:
    BlockQueue<C>* cal_bq;
    BlockQueue<S>* save_bq;
};

void *producer(void *args)
{
    BlockQueue<CalTask> *cal_bq = (static_cast<BlockQueues<CalTask, SaveTask> *>(args))->cal_bq;
    while (true)
    {
        // 生产活动
        int x = rand() % 100 + 1;
        int y = rand() % 5;
        int operCode = rand() % oper.size();
        CalTask t(x, y, oper[operCode], Add);
        cal_bq->push(t);
        std::cout << "producer thread，生产计算任务：" << t.getTask() << std::endl;
        sleep(1);
    }
    return nullptr;
}

void *consumer(void *args)
{
    // 需要消费者同时看到计算队列和保存队列，才能完成计算和保存工作
    BlockQueue<CalTask> *cal_bq = (static_cast<BlockQueues<CalTask, SaveTask> *>(args))->cal_bq;
    BlockQueue<SaveTask> *save_bq = (static_cast<BlockQueues<CalTask, SaveTask> *>(args))->save_bq;
    while (true)
    {
        // 消费活动，做为消费者
        CalTask out;
        cal_bq->pop(&out);
        std::string result = out();
        std::cout << "cal thread，完成计算任务: " << result << std::endl;
        // sleep(1);

        // 保存操作，做为生产者
        SaveTask save(result, Save);
        save_bq->push(save);
        std::cout << "cal thread，推送存储任务完成..." << std::endl; 
    }

    return nullptr;
}

void* saver(void* args)
{
    // 消费者看待
    BlockQueue<SaveTask> *save_bq = (static_cast<BlockQueues<CalTask, SaveTask> *>(args))->save_bq;
    while(true)
    {
        SaveTask st;
        save_bq->pop(&st);
        st();
        std::cout << "save thread，保存任务完成..." << std::endl; 
    }

    return nullptr;
}

int main()
{
    srand((unsigned int)time(nullptr) % 1234);

    BlockQueues<CalTask, SaveTask> bq;
    bq.cal_bq = new BlockQueue<CalTask>();
    bq.save_bq = new BlockQueue<SaveTask>();


    pthread_t p, c, s;
    pthread_create(&p, nullptr, producer, &bq);
    pthread_create(&c, nullptr, consumer, &bq);
    pthread_create(&s, nullptr, saver, &bq);

    pthread_join(p, nullptr);
    pthread_join(c, nullptr);
    pthread_join(s, nullptr);

    delete bq.cal_bq;
    delete bq.save_bq;
    return 0;
}